home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / misc1 / iv26_w30.zip / EXAMPLES / IDRAW / SLTEXT.C < prev    next >
C/C++ Source or Header  |  1992-03-04  |  7KB  |  250 lines

  1. /*
  2.  * Copyright (c) 1987, 1988, 1989 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Stanford not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Stanford makes no representations about
  11.  * the suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * STANFORD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18.  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
  20.  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  21.  */
  22.  
  23. // $Header: sltext.c,v 1.13 89/10/09 14:49:47 linton Exp $
  24. // implements class TextSelection.
  25.  
  26. #include "ipaint.h"
  27. #include "istring.h"
  28. #include "sltext.h"
  29. #include <InterViews/Graphic/label.h>
  30. #include <InterViews/textbuffer.h>
  31. #include <iostream.h>
  32.  
  33. // Both ReadTextData and Filter use this big static buffer.
  34.  
  35. static const int SBUFSIZE = 1000;
  36. static char sbuf[SBUFSIZE];
  37.  
  38. // TextSelection gets passed its graphic state and text.
  39.  
  40. TextSelection::TextSelection (const char* orig, int len, Graphic* gs) : (gs) {
  41.     Init(orig, len);
  42. }
  43.  
  44. // TextSelection reads its graphic state and text from a file.
  45.  
  46. TextSelection::TextSelection (istream& from, State* state) : (nil) {
  47.     ReadTextGS(from, state);
  48.     int len;
  49.     const char* orig = ReadTextData(from, len);
  50.     Init(orig, len);
  51. }
  52.  
  53. // Init copies the original text and appends Labels for each line of
  54. // text to the TextSelection.
  55.  
  56. void TextSelection::Init (const char* orig, int len) {
  57.     int tbufsize = max(len, 1);
  58.     tbuf = new char[tbufsize];
  59.     memmove(tbuf, orig, len);
  60.     text = new TextBuffer(tbuf, len, tbufsize);
  61.     lineHt = 0;
  62.  
  63.     int lines = text->Height();
  64.     for (int i = 0; i < lines; ++i) {
  65.     int bol = text->LineIndex(i);
  66.     int eol = text->EndOfLine(bol);
  67.     /* need this crock for now because Label(t, 0) is buggy */
  68.     if (eol - bol > 0) {
  69.         Append(new Label(text->Text(bol, eol), eol - bol));
  70.     } else {
  71.         Append(new Label(""));
  72.     }
  73.     }
  74.     ReadjustSpacing(GetFont());
  75. }
  76.  
  77. // Free storage allocated for the text in the TextSelection.
  78.  
  79. TextSelection::~TextSelection () {
  80.     delete text;
  81.     delete tbuf;
  82. }
  83.  
  84. // Copy returns a copy of the TextSelection.
  85.  
  86. Graphic* TextSelection::Copy () {
  87.     return new TextSelection(text->Text(), text->Length(), this);
  88. }
  89.  
  90. // IsA returns true if the TextSelection is a TextSelection so Editor
  91. // can identify TextSelections and edit them differently.
  92.  
  93. boolean TextSelection::IsA (ClassId id) {
  94.     return id == TEXTSELECTION || Picture::IsA(id);
  95. }
  96.  
  97. // GetOriginal returns a pointer to the TextSelection's text.
  98.  
  99. const char* TextSelection::GetOriginal (int& len) {
  100.     len = text->Length();
  101.     return text->Text();
  102. }
  103.  
  104. // ShapedBy returns true if the TextSelection intersects a box around
  105. // the given point.
  106.  
  107. boolean TextSelection::ShapedBy (Coord px, Coord py, float maxdist) {
  108.     int slop = round(maxdist / 2);
  109.     BoxObj pickpoint(px - slop, py - slop, px + slop, py + slop);
  110.     return (LastGraphicIntersecting(pickpoint) != nil);
  111. }
  112.  
  113. // draw readjusts the spacing between lines of text for a new font if
  114. // necessary and sets fillbg false and pattern solid to draw the text
  115. // like the printer will.
  116.  
  117. void TextSelection::draw (Canvas* c, Graphic* gs) {
  118.     ReadjustSpacing(gs->GetFont());
  119.     boolean fillbg = gs->BgFilled();
  120.     PPattern* pattern = gs->GetPattern();
  121.  
  122.     gs->SetPattern(psolid);
  123.     gs->FillBg(false);
  124.     Selection::draw(c, gs);
  125.     gs->FillBg(fillbg);
  126.     gs->SetPattern(pattern);
  127. }
  128.  
  129. // drawClipped readjusts the spacing between lines of text for a new
  130. // font if necessary and sets fillbg false and pattern solid to draw
  131. // the text like the printer will.
  132.  
  133. void TextSelection::drawClipped (Canvas* c, Coord l, Coord b, Coord r, Coord t,
  134. Graphic* gs) {
  135.     ReadjustSpacing(gs->GetFont());
  136.     boolean fillbg = gs->BgFilled();
  137.     PPattern* pattern = gs->GetPattern();
  138.  
  139.     gs->SetPattern(psolid);
  140.     gs->FillBg(false);
  141.     Selection::drawClipped(c, l, b, r, t, gs);
  142.     gs->FillBg(fillbg);
  143.     gs->SetPattern(pattern);
  144. }
  145.  
  146. // ReadjustSpacing recalculates the spacing between lines of text.
  147.  
  148. void TextSelection::ReadjustSpacing (PFont* font) {
  149.     if (font != nil) {
  150.     int newHt = ((IFont*) font)->GetLineHt();
  151.     if (lineHt != newHt) {
  152.         lineHt = newHt;
  153.         int vertoffset = -lineHt + 1;
  154.         for (First(); !AtEnd(); Next()) {
  155.         Graphic* label = GetCurrent();
  156.         label->SetTransformer(nil);
  157.         label->Translate(0, vertoffset);
  158.         vertoffset -= lineHt;
  159.         }
  160.     }
  161.     }
  162. }
  163.  
  164. // ReadTextData reads and returns the text contained in the PostScript
  165. // representation of the TextSelection.
  166.  
  167. const char* TextSelection::ReadTextData (istream& from, int& len) {
  168.     TextBuffer stext(sbuf, 0, SBUFSIZE);
  169.     char nl = '\n';
  170.  
  171.     if (versionnumber >= NONREDUNDANTVERSION) {
  172.     Skip(from);
  173.     int dot = 0;
  174.     char c = ' ';
  175.     while (from >> c && c != ']') {
  176.         while (c != '(' && from.get(c)) {
  177.         }
  178.         while (from.get(c) && c != ')') {
  179.         if (c == '\\') {
  180.             from.get(c);
  181.         }
  182.         stext.Insert(dot++, &c, 1);
  183.         }
  184.         stext.Insert(dot++, &nl, 1);
  185.     }
  186.     stext.Delete(--dot, 1); // buffer must not terminate in '\n'
  187.     } else {
  188.     int dot = 0;
  189.     while (from >> buf && strcmp(buf, startdata) == 0) {
  190.         char blank;
  191.         from.get(blank);
  192.         from.get(buf, BUFSIZE - 1);
  193.         int buflen = strlen(buf) + 1;
  194.         buf[buflen - 1] = '\n';
  195.         stext.Insert(dot, buf, buflen);
  196.         dot += buflen;
  197.     }
  198.     stext.Delete(--dot, 1); // buffer must not terminate in '\n'
  199.     }
  200.  
  201.     len = stext.Length();
  202.     return stext.Text();
  203. }
  204.  
  205. // WriteData writes the TextSelection's data and Postscript code to
  206. // draw it.
  207.  
  208. void TextSelection::WriteData (ostream& to) {
  209.     to << "Begin " << startdata << " Text\n";
  210.     WriteTextGS(to);
  211.     to << startdata << "\n";
  212.     to << "[\n";
  213.  
  214.     int lines = text->Height();
  215.     for (int i = 0; i < lines; ++i) {
  216.     int bol = text->LineIndex(i);
  217.     int eol = text->EndOfLine(bol);
  218.     const char* string = Filter(text->Text(bol, eol), eol - bol);
  219.     to << "(" << string << ")\n";
  220.     }
  221.  
  222.     to << "] Text\n";
  223.     to << "End\n\n";
  224. }
  225.  
  226. // Filter escapes embedded special characters that would cause syntax
  227. // errors in a Postscript string.
  228.  
  229. const char* TextSelection::Filter (const char* string, int len) {
  230.     TextBuffer stext(sbuf, 0, SBUFSIZE);
  231.     char esc = '\\';
  232.     char nul = '\0';
  233.  
  234.     int dot = 0;
  235.     for (int i = 0; i < len; i++) {
  236.     switch (*string) {
  237.     case '(':
  238.     case ')':
  239.     case '\\':
  240.         stext.Insert(dot++, &esc, 1);
  241.         // fall through
  242.     default:
  243.         stext.Insert(dot++, string++, 1);
  244.     }
  245.     }
  246.     stext.Insert(dot++, &nul, 1);
  247.  
  248.     return stext.Text();
  249. }
  250.